import enum

from fastapi import FastAPI, Depends, Query, Request
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from typing import Union, Optional, List

app = FastAPI(title="miller的第一个fastapi", description="虽然有很多问题,但还是要学习的,很高效,以后就用你了")
app.add_middleware(
    CORSMiddleware, allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

""" 这里如果用description注释,其实内部的方法注释就会消失"""


@app.get("/path1", summary="基本用法", description="传什么返回什么", tags=["path参数"])
async def path1(name: str) -> str:
    return name


class MyType(enum.IntEnum):
    OP1 = 1
    OP2 = 2


@app.get("/path2/{uid}", summary="枚举参数", description="只允许传入枚举的值,并且指定默认值", tags=["path参数"])
async def path2(uid: MyType = MyType.OP1):
    return f"your uid is:{uid}"


@app.get("/path3/{s:path}", summary="path参数类型", description="path参数可以识别特殊内容,前提是前端需要对其进行urlencode", tags=["path参数"])
async def path3(s: str):
    return f'your path is {s}'


@app.get("/query", summary="query参数", description="", tags=["query参数"])
async def query(name: str, age: int = 18):
    return {'name': name, 'age': age}


@app.get("/query1", summary="Union,Optional 使用", description="", tags=["query参数"])
async def query1(name: Union[str, int], age: Optional[int] = 18):
    return {'name': name, 'age': age}


@app.get("/query2/{db}/{table}", summary="path query混合使用", description="", tags=["query参数"])
async def query2(db: str, table: str, select: str, where: Optional[str] = None, limit: Optional[int] = None,
                 offset: Optional[int] = None):
    s = f'select {select} from {db}.{table} '
    if where:
        s += f'where{where} '
    if limit:
        s += f'limit {limit} '
    if offset:
        s += f'offset {offset} '
    return s


async def cmd_param(select: str = "*", limit: int = 10, offset: int = 100):
    # 当多个地方都用到这样的数据时,就可以避免很多重复劳动了
    return {'select': select, 'limit': limit, 'offset': offset}


@app.get("/query3/", summary="depends使用,把多个参数提出外部处理", description="", tags=["query参数"])
async def query3(cmd: dict = Depends(cmd_param)):
    return cmd


# query类的使用########################################################################################
@app.get("/q1/", summary="query类基本使用", description="可以限制长度或者正则匹配等", tags=["query类"])
async def q1(pwd: Optional[str] = Query('123456', max_length=12, min_length=6, regex='^[a-zA-Z0-9]{6,15}$')):
    return pwd


@app.get("/q2/", summary="使用typing的List获取数组参数传入", description="...表示为必传参数", tags=["query类"])
async def q2(pwd: List[str] = Query(..., description='密码:...表示必传'),
             a: List[str] = Query(None, description='a: query里面默认为None,可以为空')):
    return [pwd, a]


@app.get("/q3/", summary="别名使用", description="python中的变量名不能有-等特殊符号,但是传入的参数必须是带这些特殊符号的,这时候就可以用别名", tags=["query类"])
async def q3(pwd: List[str] = Query(..., alias="-my-pwd", max_length=6,
                                    description='方法里面的参数为pwd,但是别名不同,这里用户实际传值的时候就需要用别名作为key来传了')):
    return pwd


if __name__ == "__main__":
    uvicorn.run("main:app", host='0.0.0.0', port=8000, reload=True)
